"use strict"
/*
2013-09-25 - Al C - version 1.0.10 - added projected monthly total usage; config alerts if values in config.js do not match localStorage; KB-auto code
2013-09-30 - Al C - version 1.0.11A - initial integration of the traff daemon results
2013-10-01 - Al C - version 1.0.11B - more integration of the traff daemon results
2013-10-06 - Al C - version 1.0.12 - incorporating & extending whitebeards's colours patch
*/
var _rs_Date,_re_Date, _cr_Date, _resetDay
var countdown
var oDevicesHash, oDataHash
var devices=[],names=[],usage=[]
var colours_list=['AliceBlue','DarkOliveGreen','Indigo','MediumPurple','Purple','DarkOrange','MediumSeaGreen','Red','Aqua','DarkOrchid','Khaki','MediumSlateBlue','RosyBrown','AquaMarine','DarkRed','MediumSpringGreen','RoyalBlue','DarkSalmon','LavenderBlush','MediumTurquoise','SaddleBrown','DarkSeaGreen','LawnGreen','MediumVioletRed','Salmon','DarkSlateBlue','LemonChiffon','MidnightBlue','SandyBrown','Black','DarkSlateGray','LightBlue','MintCream','SeaGreen','BlanchedAlmond','DarkTurquoise','MistyRose','SeaShell','Blue','DarkViolet','LightCyan','Moccasin','Sienna','BlueViolet','DeepPink','LightGoldenrodYellow','NavajoWhite','Silver','Brown','DeepSkyBlue','LightGray','Navy','SkyBlue','BurlyWood','DimGray','LightGreen','SlateBlue','CadetBlue','DodgerBlue','LightPink','Olive','SlateGray','Chartreuse','FireBrick','LightSalmon','OliveDrab','Snow','Chocolate','LightSeaGreen','Orange','SpringGreen','Coral','ForestGreen','LightSkyBlue','OrangeRed','SteelBlue','CornFlowerBlue','Fuchsia','LightSlateGray','Orchid','Tan','Cornsilk','Gainsboro','LightSteelBlue','PaleGoldenRod','Teal','Crimson','GhostWhite','LightYellow','PaleGreen','Thistle','Cyan','Gold','Lime','PaleTurquoise','Tomato','DarkBlue','GoldenRod','LimeGreen','PaleVioletRed','Turquoise','DarkCyan','Gray','PapayaWhip','Violet','DarkGoldenRod','Green','Magenta','PeachPuff','Wheat','DarkGray','GreenYellow','Maroon','Peru','White','DarkGreen','HoneyDew','MediumAquaMarine','Pink','DarkKhaki','HotPink','MediumBlue','Plum','Yellow','DarkMagenta','IndianRed','MediumOrchid','PowderBlue','YellowGreen','AntiqueWhite','Ivory','Beige','WhiteSmoke','Bisque','Linen','OldLace','LightCoral','Lavender','Azure','FloralWhite']
var dispUnits=['b','Kb','MB','GB','TB','PB']
var mb_dates=[], traff=[]
var g_router=[], g_isp=[], g_ispdelta=[], g_cummulative=[],corrections=[]
var toMB,toGB

Object.getPrototypeOf(localStorage).find = function(s) {
	var r=[]
	Object.keys(localStorage).forEach(function(k){
		if (k.indexOf(s)!= -1) r.push({'key':k,'value':localStorage.getItem(k)});
	});
	return r.sort(function(a, b) { return (a.key < b.key?1:(a.key > b.key?-1:0)); });
}
Object.getPrototypeOf(localStorage).Clear = function(s) {
	if(confirm('Are you sure you want to clear the contents of localStorage?  This cannot be undone!')){
		Object.keys(localStorage).forEach(function(k){
			localStorage.removeItem(k)
		});
	}
}
$(document).ready(function (){
	$('#error-notification').remove()
	$('input:radio').change(function(){
		$('.is-cap')[$('#bandwidth-u').is(':checked')?'hide':'show']()
		if($('#bandwidth-l').is(':checked')){
			$('#bw_cap').select();
		}
		else{
			$('#bw_cap').addClass('disabled');
			localStorage.setItem('bw_cap','')
			$('#spUsageCap').text('Unlimited').removeClass('GBytes')
		}
	})
	$('#bw_cap').focus(function(){
		$(this).removeClass('disabled')
		$('#bandwidth-l').prop('checked','checked')
		$('#bandwidth-u').prop('checked','')
	})
	$('#bw_cap').blur(function(){
		var band_cap=$(this).val();
		if(isNaN(band_cap)||band_cap<=0){
			$(this).addClass('badvalue');
			alert('The bandwidth allowance must be a positive number!\n\nPlease try again.');
		}
		else{
			$('#spUsageCap').text(band_cap).addClass('GBytes')
			localStorage.setItem('bw_cap',band_cap)
			UsageHistoryChart()
		}
	   $('.is-cap')[$('#bandwidth-l').is(':checked')?'show':'hide']()
	})
	$('.tab-name').click(function(){
		if(! $(this).hasClass('not-selected')) return;
		$(this).siblings().addClass('not-selected');
		$(this).removeClass('not-selected');
		var tab_id= '#'+$(this).attr('id')+'-section';
		$(tab_id).siblings('div').hide();
		$(tab_id).show();
	})
	$('#showHourly,#showLive,#showISP').change(function(){
		var isChecked=$(this).is(':checked');
		var tid=$(this).attr('id');
		$('.'+tid)[isChecked?'slideDown':'slideUp']('slow');
		localStorage.setItem(tid,isChecked)
		if(tid=='showISP' && isChecked){
			ISP_Change()
		}
		else if(tid=='showHourly' && isChecked){
			loadHourly()
		}
	})
	$('#data-tabs .tab-name').click(function(){
		var clicked_tab=$(this).attr('id')
		load_view(clicked_tab)
   })
   $('#NumDecimals,#DisplayBase,#DisplayUnits').change(function(){
		displayBytes('#pageContent')
		localStorage.setItem('DisplayUnits', $('#DisplayUnits').val())
		localStorage.setItem('DisplayBase', $('#DisplayBase').val())
		localStorage.setItem('NumDecimals', $('#NumDecimals').val())
		var du=$("#DisplayUnits").val()
		$("#spBandwidth").html(du=="auto"?"automatically sized.":'in '+dispUnits[du]+'ytes.');
		var base=$("#DisplayBase").val();
		toMB=Math.pow(base,2)
		toGB=Math.pow(base,3)
	 });
	$('#dataPath,#usagefile,#devicefile,#hourFileName').change(function(){
		var tid=$(this).attr('id'), tv=$(this).val()
		$('.'+tid).text(tv);
		localStorage.setItem(tid,tv)
		if(tid=='devicefile'){
			load_devices()
		}
		else{
			load_data()
		}
	});
	$("#fDBtn").click(function (){
		_cr_Date=_rs_Date
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	});
	$(".pDBtn").click(function (){
		$('#bnav button').hide()
		_cr_Date=newdate(_cr_Date,-1)
		if(_cr_Date<_rs_Date){
			_cr_Date=_rs_Date
			return
		}
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	});
	$(".nDBtn").click(function (){
		$('#bnav button').hide()
		_cr_Date=newdate(_cr_Date,1)
		if(_cr_Date>_re_Date){
			_cr_Date=_re_Date
			return
		}
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	});
	$("#lDBtn").click(function (){
		_cr_Date=_re_Date
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	});
	$('.go2today').click(function(){
		_cr_Date=new Date()
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	})
	$(".linked").change(function(e){
		var tid=$(this).attr('id'), tv=$(this).val()
		if(tid=='reset_day'&&(tv==undefined||tv==''||isNaN(tv))){
			alert("Sorry this field cannot be empty and must be a number!")
			$('#'.tid).select()
			e.stopPropagation()
			return false
		}
		$('.'+tid).html(tv+(tid=='reset_day'?'<sup>'+((tv%10==1)?'st':((tv%10==2)?'nd':'th'))+'</sup>':''))
		localStorage.setItem(tid,tv)
	});
	$(".linkedURL").change(function(){
		var tid=$(this).attr('id'), tv=$(this).val()
		$('.'+tid).prop('href',tv);
		localStorage.setItem(tid,tv)
	});
	$("#ShowZeroes,#ShowDevices").change(function(){
		showHideDevices();
		localStorage.setItem('ShowZeroes',$('#ShowZeroes').is(':checked'))
		localStorage.setItem('ShowDevices',$('#ShowDevices').is(':checked'))
	});
	$('#Refresh').click(function(){
		load_data();
		$("#RefreshInterval").html($("#RefreshInterval").val());
	});
	$('#Reset').click(function(){
		$("#RefreshInterval").html($("#RefreshInterval").val());
	});
	$('#StartPause').click(function(){
		if($(this).text()=='Pause'){
			clearInterval(countdown);
			$(this).text('Start')
			$('#Reset,#Refresh').fadeOut('slow')
	   }
		else{
			countdown=setInterval(countdownFunc,1000);
			$(this).text('Pause')
			$('#Reset,#Refresh').fadeIn('slow')
	   }
	});
	$("#mb-filter").change(function(){
		$('#monthly-breakdown-tab').removeClass('loaded')
		load_view('monthly-breakdown-tab',true)
		flushChanges('#monthly-breakdown-table');
	});
	$('.expand').click(function(){
		$('.expand').removeClass('hidden')
		$(this).addClass('hidden')
		$('.changes').find('ul').slideUp('slow')
		$(this).parent('.changes').find('ul').slideDown('slow')
	})
	$('#add-history').click(function(){
		var lr = $('.summary-row').last().attr('id').split('-');
		var mo=(lr[2]==1?12:lr[2]-1)
		var yr=lr[1]-(mo==12?1:0)
		var hid='bill-'+yr+'-'+twod(mo)+'-'+twod(lr[3])
		localStorage.setItem(hid,'0;0')
		load_data(hid)
	})
	$('#correction-row input').change(function(){
		$('.badvalue').removeClass('badvalue')
		if($(this).hasClass('cf-desc')){}
		else if(isNaN($(this).val())){
			$(this).addClass('badvalue')
			alert('This value must be a number!')
			$(this).select()
			return false
		}
		$('#monthly-tab,#monthly-breakdown-tab').removeClass('loaded')
		var desc=$('.cf-desc').val()
		var tdu=$('.cf-u input').val(),tdd=$('.cf-d input').val()
		var cd=_cr_Date.getDate()
		var da=twod(_rs_Date.getDate())
		var mo=twod(_rs_Date.getMonth()+1)
		var yr=_rs_Date.getFullYear()
		var ds=yr+'-'+mo+'-'+da

		var dcvd=(tdd-(corrections[cd]==null?0:corrections[cd].down))*toMB
		var dcvu=(tdu-(corrections[cd]==null?0:corrections[cd].up))*toMB
		if(desc==''&&(tdu==''||tdu==0)&&(tdd==''||tdd==0)){
			delete corrections[cd]
		}
		else{
			corrections[cd]={desc:desc,down:tdd, up:tdu}
		}
		localStorage.setItem('corrections'+'-'+mo+'-'+yr, JSON.stringify(corrections))
		tdu=tdu*toMB
		tdd=tdd*toMB
		$('#correction-row .TotalBytes ').attr('value',tdu+tdd)
		$('#DailyData .is_d').each(function(){
			tdd+=Number($(this).find('.downloads').attr('value'))
			tdu+=$(this).find('.uploads').attr('value')*1
		})
		$('#dailyFooter .downloads').attr('value',tdd)
		$('#dailyFooter .uploads').attr('value',tdu)
		$('#dailyFooter .TotalBytes ').attr('value',tdu+tdd)
		var ctb=Number($('#bill-'+ds+' .TotalBytes ').attr('value'))
		var ctbd=Number($('#bill-'+ds+' .downloads ').attr('value'))
		var ctbu=$('#bill-'+ds+' .uploads ').attr('value')*1
		$('#bill-'+ds+' .TotalBytes ').attr('value', ctb+dcvd+dcvu )
		$('#bill-'+ds+' .downloads ').attr('value', ctbd+dcvd )
		$('#bill-'+ds+' .uploads ').attr('value', ctbu+dcvu )

		displayBytes('#dailyFooter,#correction-row,#bill-'+ds);
		setPercents('#DailyData tr,#correction-row', tdu+tdd)
		if($('#daily-tab').hasClass('loaded'))DrawPie('Daily');
		if($('#monthly-tab').hasClass('loaded'))DrawPie('Monthly');

	})
	setFormDefaults()

	$('.required').parents('p').each(function(){
		if($(this).attr('id')==undefined)return
		var id=$(this).attr('id').split('-')[1]
		if(localStorage.getItem(id)==undefined){
			$(this).append("<span class='mval'>[&nbsp;&#x2714;&nbsp;]</span>")
		}
		$('#'.id).addClass('mval')
		var mc=$('.mval').length-1
		$('#missing-txt').text("You are currently missing "+ mc +" required value"+(mc==1?'':'s')+".")
	})
	$('.mval').click(function(){
		var id=$(this).parents('p').attr('id').split('-')[1]
		if(id=='reset_day'&&($('#reset_day').val()==undefined||$('#reset_day').val()==''||isNaN($('#reset_day').val()))){
			alert("Sorry this field cannot be empty and must be a number!")
			$('#'.tid).select()
			return false
		}
		localStorage.setItem(id, $('#'+id).val())
		$(this).remove()
		var mc=$('.mval').length-1
		$('#missing-txt').text("You are currently missing "+ mc +" required value"+(mc==1?'':'s')+".")
		if(mc==0){
			alert("Congratulations, all required values have now been specified.  The page will now reload.")
			window.location='yamon.html'
		}
	})
	if(localStorage.getItem('reset_day')==undefined||localStorage.getItem('bw_cap')==undefined||localStorage.getItem('dataPath')==undefined||localStorage.getItem('devicefile')==undefined||localStorage.getItem('usagefile')==undefined){
		$('#SECTION_TWO,#summary-tab-section,.tabs,#p-timer').hide()
		$('.intro,#settings-tab-section,#missing-txt').slideDown('slow')
	}
	else{
		load_devices()
		setSummaryTotals();
	}
	if(_traff_daemon=='1'){
		$('.is_td').show()
	}
})
function twod(v){
	return ('0'+Number(v)).slice(-2)
}
function setFormDefaults(){
	var bw_cap=localStorage.getItem('bw_cap')
	if(bw_cap==undefined){
	}
	else if(bw_cap==''){
		$('#bandwidth-u').prop('checked','checked')
		$('#spUsageCap').text('Unlimited').removeClass('GBytes')
	}
	else{
		$('#bandwidth-l').prop('checked','checked')
		$('#spUsageCap').text(bw_cap).addClass('GBytes')
		$('#bw_cap').val(bw_cap)
	}
	var config_issues='';
	if(localStorage.getItem('reset_day')!=_ispBillingDay){
	   config_issues+='- reset day ('+localStorage.getItem('reset_day')+')does not match the value of _ispBillingDay` ('+_ispBillingDay+')'
	}
	if(localStorage.getItem('dataPath')!=_wwwData){
	   config_issues+=(config_issues==''?'':'\n')+'- Path to Data ('+localStorage.getItem('dataPath')+') does not match the value of _wwwData` ('+_wwwData+')'
	}
	if(localStorage.getItem('devicefile')!=_usersFileNameWWW){
	   config_issues+=(config_issues==''?'':'\n')+'- Users & Devices file name ('+localStorage.getItem('devicefile')+') does not match the value of _usersFileNameWWW` ('+_usersFileNameWWW+')'
	}
	if(localStorage.getItem('usagefile')!=_usageFileName){
	   config_issues+=(config_issues==''?'':'\n')+'- Usage file name ('+localStorage.getItem('usagefile')+') does not match the value of _usageFileName` ('+_usageFileName+')'
	}
	var t_sh=localStorage.getItem('showHourly')=='true'?1:0
	if(t_sh!=_doHourlyData){
	   config_issues+=(config_issues==''?'':'\n')+'- Show hourly checkbox value ('+t_sh+') does not match the value of _doHourlyData` ('+_doHourlyData+')'
	}
	if(localStorage.getItem('showHourly')&&(localStorage.getItem('hourFileName')!=_hourlyFileName)){
		if(!localStorage.getItem('hourFileName')){
			localStorage.setItem('hourFileName',_hourlyFileName)
		}
		else{
			config_issues+=(config_issues==''?'':'\n')+'- Hourly usage file name ('+localStorage.getItem('hourFileName')+') does not match the value of _hourlyFileName` ('+_hourlyFileName+')'
		}
	}
	if(config_issues!=''){
		 alert("There are some discrepancies between your saved report settings and the values in your `config.file`:\n"+config_issues+"\n\nPlease check your inputs on the `Settings` tab and ensure they are consistent with your `config.file`!\n\nIf you are viewing these reports for the first time, the next screen will help you enter those values.\n\nIf you've just updated your YAMon installation, Al probably put his `config.file` into the zip file (and that has clobbered your previous settings)... sorry about that!")

	}
	$('#reset_day').val(localStorage.getItem('reset_day')||_ispBillingDay)
	_resetDay=$('#reset_day').val()
	$('.reset_day').html(_resetDay+'<sup>'+((_resetDay%10==1)?'st':((_resetDay%10==2)?'nd':'th'))+'</sup>')
	$('#DisplayUnits').val(localStorage.getItem('DisplayUnits')||'auto');
	var du=$("#DisplayUnits").val()
	$('.change-units a')[du=='auto'?'first':'last']().show()
	$('.change-units a').click(function(){
		changeUnits(this)
	})	
	$("#spBandwidth").html(du=="auto"?"automatically sized.":'in '+dispUnits[du]+'ytes.');
	$('#DisplayBase').val(localStorage.getItem('DisplayBase')||'1024');
	$('#NumDecimals').val(localStorage.getItem('NumDecimals')||'1');
	$('#RefreshInterval').val(localStorage.getItem('RefreshInterval')||'120');
	$('.RefreshInterval').text($('#RefreshInterval').val());
	$('#ShowZeroes,#ShowDevices,#showHourly,#showLive,#showISP').each(function(){
		$(this).prop('checked',eval(localStorage.getItem($(this).attr('id'))));
	})
	$('#showHourly,#showLive,#showISP').each(function(){
		$('.'+$(this).attr('id'))[$(this).is(':checked')?'show':'hide']()
	})
	$('#dataPath').val(localStorage.getItem('dataPath')||_wwwData);
	$('#devicefile').val(localStorage.getItem('devicefile')||_usersFileNameWWW);
	$('#usagefile').val(localStorage.getItem('usagefile')||_usageFileName);
	$('#hourFileName').val(localStorage.getItem('hourFileName')||_hourlyFileName);
	$('#liveFileName').val(localStorage.getItem('liveFileName')||'live_data.html');
	$('#isp-name').val(localStorage.getItem('isp-name')||'ISP');
	$('.isp-name').text($('#isp-name').val());
	$('#isp-url').val(localStorage.getItem('isp-url'));
	$('.isp-url').prop('href',$('#isp-url').val());

	var base=$("#DisplayBase").val();
	toMB=Math.pow(base,2)
	toGB=Math.pow(base,3)

}
function setSummaryTotals(){
	flushChanges();
	var report=localStorage.find('bill')
	Object.keys(report).forEach(function(k){
		var bill=report[k].key
		var de = bill.split('-')
		var yr=de[1]
		var mo=de[2]
		var da=de[3]
		var values = report[k].value.split(';')
		var up=Number(values[0])
		var down=Number(values[1])
		var nr=$('<tr/>').attr('id',bill).addClass('summary-row')
		nr.append($('<td/>').text(yr+'-'+mo+'-'+da).addClass('interval br'))
		nr.append($('<td/>').addClass('downloads num').attr('value',down))
		nr.append($('<td/>').addClass('uploads num  br').attr('value',up))
		nr.append($('<td/>').addClass('TotalBytes str num').attr('value',up+down))
		nr.append($('<td/>').addClass('is-cap cap GBytes').html($('#bw_cap').val()))
		nr.append($('<td/>').addClass('percent is-cap'))
		nr.append($('<td/>').addClass('a-c').html("<span class='rmls' title='Delete this interval' onclick=delLS('"+bill+"')>[ - ]</span>"))
		$('#SystemTotalsTable').append(nr)

	})
	$('.is-cap')[$('#bandwidth-u').is(':checked')?'hide':'show']()
	if(!$('#bandwidth-u').is(':checked')){
		setPercents('.summary-row', $('#bw_cap').val()*toGB)
	}
	UsageHistoryChart()
   $('.interval').click(function(){
		var lr=$(this).parents('tr').attr('id')
		var fr=$('#SystemTotalsTable .summary-row').first().attr('id')
		$('#DailyData,#MonthlyData,#MonthlyBreakdown').html('')
		if(lr==fr){
			load_data()
		}
		else{
			var hid=lr.split('-')
			hid[0]='history'
			load_data(hid.join('-'))
		}
		$('.currentSummary').removeClass('currentSummary')
		$(this).parent().addClass('currentSummary')
	})
	displayBytes('#SystemTotalsTable');
}

var hashCode=function(s){
	return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}

function load_devices(){
	$('.loading').text('Loading devices...').show();
	$('.loaded').removeClass('loaded');
	var device_file=$('#dataPath').val()+$('#devicefile').val()
	$.get(device_file)
	.done(function(list,textStatus){
		var nDevicesHash=hashCode(list);
		if(oDevicesHash!=nDevicesHash){
			devices=[]
			var ul=list.split('\n'),n=1
			$.each(ul, function(){
				if(this=='') return;
				var row=this.split(',')
				var mac=row[0].toUpperCase()
				var uid=hashCode(mac)
				devices[mac]={un:n,id:uid,ip:row[1],name:row[2],device:row[3],down:0,up:0,colour:row[4]}
				if(row[4]!=null){
					var index = (colours_list.join(",").toLowerCase().split(",")).indexOf((row[4]).toLowerCase());
					if(index!=-1){
					   colours_list.splice(index, 1);
					}
				}
				names[row[2]]={down:0,up:0}
				n++
			});
			devices
			if(_traff_daemon=='1'){
				devices['FF:FF:FF:FF:FF:FF']={un:n,id:'000000',ip:'1.1.1.1',name:'Router',device:'traff daemon',down:0, up:0}
			}
			oDevicesHash=nDevicesHash
			var sel=$("#mb-filter").val()
			$("#mb-filter").html('<option value="dd-ALL">ALL Traffic By Day</option>');
			Object.keys(devices).sort(byName).forEach(function(d){
				var id=devices[d].id
				var un=devices[d].name
				var u_n=clean(un)
				var ud=devices[d].device
				var u_d=clean(ud)
				$("#mb-filter").append($("<option/>").attr('id','mbd-'+id).attr('value','dd-'+u_n+'-'+u_d).text(ud).addClass('ddl-d du-'+u_n));
			})
			Object.keys(names).forEach(function(n){
				var nn=clean(n)
				$(".du-"+nn).first().before($("<option/>").attr('id','mbd-'+nn).attr('value','dd-'+nn).text(n).addClass('ddl-u du-'+nn));
			})
			var show_devices=$('#ShowDevices').is(':checked')
			$('.ddl-device')[show_devices?'removeClass':'addClass']('hidden');
			$("#mb-filter").val(sel)
	}
		else{
		}
		clearInterval(countdown)
		countdown=setInterval(countdownFunc,1000)
		load_data()
	})
	.fail(function(jqxhr,settings,exception){
		alert("Could not load the devices file.\n\nPlease check your parameters on the Settings tab.\n\nAlso, check the file to ensure that the first line is not blank... for some oddball reason that is causing the loading process to fail?!?");
		$('#settings-tab').click()
	})
	$('.loading').fadeOut(1500)
}
function zeroDevicesTotal(){
	Object.keys(devices).forEach(function(k){
		devices[k].up=0
		devices[k].down=0
	})
	Object.keys(names).forEach(function(k){
		names[k].up=0
		names[k].down=0
	})
}
function load_data(ri){
   var da,mo,yr
   if(Object.keys(names).length==0){
		alert('Uh-oh!!  No names/devices were read from the devices file?!?\n\nPlease check the `devices` field on the Settings tab to ensure that it is pointing to the correct filename')
		return false
	}
	$('.loading').text('Loading data file...').show();
	$('.loaded').removeClass('loaded');
	var loading_history=false
	if(typeof(ri)!='undefined'){
		loading_history=true
	}
	_resetDay=$('#reset_day').val()
	var rd=twod(_resetDay)
	if(loading_history){
		var de=ri.split('-')
		da=twod(de[3])
		mo=twod(de[2])
		yr=de[1]
		clearInterval(countdown);
		$('#p-timer').fadeOut('slow')
		_rs_Date= new Date(yr,mo-1,da);
		var rm=twod(_rs_Date.getMonth()-(-1))
		_re_Date=new Date(yr,mo,da-1);
		_cr_Date=_rs_Date
	}
	else{
		_cr_Date=new Date();
		da=_cr_Date.getDate()
		var da2=twod(da)
		mo=twod(_cr_Date.getMonth()-(-1))
		yr=_cr_Date.getFullYear()
		clearInterval(countdown);
		countdown=setInterval(countdownFunc,1000);
		$('#p-timer').fadeIn('slow')
		_rs_Date=new Date(yr,mo-(da>=_resetDay?1:2),_resetDay);
		var rm=twod(_rs_Date.getMonth()-(-1))
		_re_Date=new Date(yr,mo-(da>=_resetDay?0:1),_resetDay-1, 23, 59, 59);
		$('.interval').first().parent().addClass('currentSummary')
		var bps=$('.summary-row').first().find('.TotalBytes').attr('value')/((_cr_Date-_rs_Date))
		var etb=bps*((_re_Date-_rs_Date))
		$('.summary-row').first().find('td').last().attr('value',etb).addClass('num').attr('id','estimatedMonthlyTotal').attr('title','Projected monthly total ')
		if($('#estimatedMonthlyTotal').attr('value')>Number($('#spUsageCap').text())*toGB){
			$('#estimatedMonthlyTotal').addClass('over-cap')
		}
	}
	$('.go2today')[loading_history?'fadeIn':'fadeOut']('slow')
	$('.today').text(_rs_Date.toDateString());
	corrections=JSON.parse(localStorage.getItem('corrections'+'-'+rm+'-'+yr))
	if(corrections==null){
		corrections=new Object()
	}
	var datafile=$('#dataPath').val()+rd+'-'+rm+'-'+yr+'-'+$('#usagefile').val()

	$('.current-interval').text(_rs_Date.toDateString() + ' - ' + _re_Date.toDateString());
	$.get(datafile)
	.done(function(dlist,textStatus){
		var nDataHash=hashCode(dlist);
		flushChanges();
		if(oDataHash!=nDataHash){
			var dl=dlist.split('\n'),tup=0,tdown=0
			usage=[]

			zeroDevicesTotal()
			$.each(dl, function(){
				if(this=='') return false;
				var dr=this.split(',')
				var mac=dr[0].toUpperCase()
				var ddown=Number(dr[2]),dup=Number(dr[3])
				if(mac=='FF:FF:FF:FF:FF:FF'){
					ddown=ddown*toMB
					dup=dup*toMB
				}
				if(devices[mac]===undefined){
					devices[mac]={id:'unknown',ip:dr[1],name:'Unknown',device:'Unknown',down:0, up:0}
				}
				usage.push({mac:mac,name:devices[mac].name,down:ddown,up:dup,date:twod(dr[4])})
				var name=devices[mac].name
				devices[mac].down+=ddown
				devices[mac].up+=dup
				if(mac=='FF:FF:FF:FF:FF:FF'){
				}
				else{
					names[name].down+=ddown
					names[name].up+=dup
					tdown+=ddown
					tup+=dup
				}
			});
			oDataHash=nDataHash

			for(var d in corrections){
				if(corrections[d]){
					tup+=corrections[d].up*toMB
					tdown+=corrections[d].down*toMB
			   }
			}

			var bill='bill-'+yr+'-'+rm+'-'+rd
			localStorage.setItem(bill,tup+';'+tdown);

			if($('#'+bill).length==0){
				var nr=$('<tr/>').attr('id',bill).addClass('summary-row')
				nr.append($('<td/>').text(yr+'-'+rm+'-'+rd).addClass('interval br'))
				nr.append($('<td/>').addClass('downloads num').attr('value',tdown))
				nr.append($('<td/>').addClass('uploads num br').attr('value',tup))
				nr.append($('<td/>').addClass('TotalBytes num').attr('value',tup+tdown))
				nr.append($('<td/>').addClass('percent is-cap'))
				nr.append($('<td/>').html("<span class='rmls' title='Delete this interval' onclick=delLS('"+bill+"')>[ - ]</span>"))
				$('#SystemTotalsTable').append(nr)
			}
			else{
				var arr=[[' .downloads',tdown], [' .uploads',tup], [' .TotalBytes',tup+tdown]]
				updateRow(bill,arr)
			}
			if($('#bandwidth-l').is(':checked')){
				setPercents('#'+bill, $('#bw_cap').val()*toGB)
			}
			displayBytes('#'+bill);
			var current_view=$('#data-tabs .tab-name').not('.not-selected').attr('id');
			load_view(current_view, loading_history);

		}
		else{
		}
	})
	.fail(function(jqxhr,settings,exception){
		alert("Could not load the data file for the date interval... the file (likely) does not exist .\n\nThe history entry will be removed from the list.");
	})
	.always(function(dlist,textStatus) {
		if(dlist==''){
			alert('Uh-oh!!  No data was read from the usage file?!?\n\nPlease ensure that the following file actually exists: \n   `'+datafile+'`')
			return false
		}
	   UsageHistoryChart()
		$('.loading').fadeOut(1500);
	})
}
function loadHourly(){
	var hourly=[]
	if(!$("#showHourly").is(':checked')) return false;
	var dec=$("#NumDecimals").val()||2;
	var da=twod(_cr_Date.getDate())
	var mo=twod(_cr_Date.getMonth()-(-1))
	var yr=_cr_Date.getFullYear()
	var datafile=$('#dataPath').val()+da+'-'+mo+'-'+yr+'-'+$('#hourFileName').val()
	$.get(datafile)
	.done(function(dlist,textStatus){
		if(dlist.length==0){
			$('#hourlyGraph').html('<h2 style="margin-left:300px;">No hourly data available!</h2>')
			var tmp=$( "h2:contains('No hourly data')" ).offset()
			$('#bnav').offset({top:tmp.top+2,left:tmp.left-40})
		   $('#bnav button').fadeIn('slow')
			return false
		}
		var dl=dlist.split('\n')
		$.each(dl, function(){
			if(this=='') return false;
			var dr=this.split(',')
			var mac=dr[0].toUpperCase()
			var hdown=Number(dr[2]),hup=Number(dr[3])
			var hr=Number(dr[4])
			if(hourly[mac]===undefined){
				hourly[mac]={name:'',usage:[]}
				for(var x=0;x<24;x++){
					hourly[mac].usage[x]=null
				}
			}
			hourly[mac].name=devices[mac].name
			hourly[mac].device=devices[mac].device
			hourly[mac].usage[hr]=Number(((hdown+hup)/toMB).toFixed(dec))
		});

 		var devicecolours=[]
		var hdata=new google.visualization.DataTable();
		hdata.addColumn('string','Name');
		Object.keys(hourly).sort(byName).forEach(function(k){
			hdata.addColumn('number', hourly[k].device+'('+hourly[k].name+')')
			var tcolour=devices[k].colour==null?colours_list[devices[k].un]:devices[k].colour
			devicecolours.push(tcolour);
		})
		for(var x=0;x<24;x++){
			var vv=[twod(x)]
			Object.keys(hourly).sort(byName).forEach(function(k){
				vv.push(hourly[k].usage[x])
			})
			hdata.addRow(vv);
		}
		var baroptions={width:900,height:400,title:'Hourly Totals',legend:{position:'right',textStyle:{fontSize:11}},chartArea:{width:'70%',height:'75%'},isStacked:true,is3D:true,hAxis:{title:'Hour of the Day - '+$('#current-date').text(),slantedText:false,titleTextStyle:{color:'green'},textStyle:{fontSize:11}},vAxis:{title:'Total Usage in MB',titleTextStyle:{color:'green'}}};
		baroptions.colors=devicecolours /* !@#$ */
		var chart=new google.visualization.ColumnChart(document.getElementById('hourlyGraph'));
		chart.draw(hdata,baroptions);
		var tmp=$( "text:contains('Hour of the Day')" ).offset()
		$('#bnav').offset({top:tmp.top,left:tmp.left-40})
		$('#bnav button').fadeIn('slow')
	})
	.fail(function(jqxhr,settings,exception){
		alert('Sorry - there was an error attempting to read the hourly data file: ' + datafile)
	})
	.always(function(dlist,textStatus) {

	})
}
function countdownFunc(){
	$(".RefreshInterval").text(Number($(".RefreshInterval").html())-1);
	if ($(".RefreshInterval").text()==0){
		load_devices();
		$(".RefreshInterval").html($("#RefreshInterval").val());
	}
}
function load_view(wv,cleardata){
	if(! $('#'+wv).hasClass('loaded')){
		$('.loading').text('Loading view...').show();
		$('#'+wv).addClass('loaded');
		switch(wv){
			case 'daily-tab':
				if(cleardata){
					$('#DailyData').html('')
				}
				setDailyTab()
				if($('#showHourly').is(':checked')){
					loadHourly()
				}
				break;
			case 'monthly-tab':
				if(cleardata){
					$('#MonthlyData').html('')
				}
				setMonthlyTab()
				break;
			case 'monthly-breakdown-tab':
				if(cleardata){
					$('#MonthlyBreakdown').html('')
				}
				monthlyBreakdown()
				break;
			case 'devices-tab':
				setDevicesTab()
				break;
		}
	}
	changelegend()

	if($('#'+wv).hasClass('not-selected')) {
		$('#'+wv).siblings().addClass('not-selected');
		$('#'+wv).removeClass('not-selected');
		var tab_id= '#'+wv+'-section';
		$(tab_id).siblings('div').hide();
		$(tab_id).show();
	};
	showHideDevices()
	$('.loading').fadeOut(1500);
}

function setDailyTab(){
	var tag=$("#DailyData");
	var today=new Date();
	_cr_Date=_cr_Date||today
	$('.current-date').text(_cr_Date.toDateString());
	$('.go2today')[$('.interval').first().parent().hasClass('currentSummary')?(_cr_Date==today?'fadeOut':'fadeIn'):'fadeOut']('slow');
	$('#tdaemon, #tdaemon-diff').remove()
	var cd=_cr_Date.getDate()
	var mo=_rs_Date.getMonth()+1
	var yr=_rs_Date.getFullYear()
	if(corrections==null||corrections[cd]==null){
		$('#correction-row,#remove-correction').hide()
		var cdu=0,cdd=0,cddesc=''
		var has_corr=0
		$('#add-correction').slideDown('slow')
	}
	else{
		$('#correction-row,#remove-correction').show()
		$('#add-correction').hide()
		var cddesc=corrections[cd].desc,cdu=corrections[cd].up,cdd=corrections[cd].down
		var has_corr=1
	}
	$('.cf-desc').val(cddesc)
	$('.cf-u input').val(cdu)
	$('.cf-d input').val(cdd)
	var current_day=twod(_cr_Date.getDate())
	var dnames=[]
	var dataset=getUsage('date',current_day)
	var nrd=dataset.length+has_corr

	var utot=cdu*toMB,dtot=cdd*toMB
	var total=utot+dtot
	$('#correction-row .TotalBytes').attr('value',utot+dtot)
	var tdaemon='', tdaemon_diff=''
	dataset.forEach(function(k){
		var dmac=k.mac
		var un=devices[dmac].name
		var u_n=clean(un)
		var dip=devices[dmac].ip
		var dn=devices[dmac].device
		var d_n=clean(dn)
		var did='dd-di-'+devices[dmac].id
		var up=k.up,down=k.down,dt=up+down
		if (dmac=="FF:FF:FF:FF:FF:FF") { 
			tdaemon=$('<tr/>').attr('id','tdaemon')
			tdaemon.append($('<td/>').addClass('deviceName br a-r').text(dn).attr('title', dmac+' | '+dip))
			tdaemon.append($('<td/>').addClass('downloads num').attr('value',down))
			tdaemon.append($('<td/>').addClass('uploads num br').attr('value',up))
			tdaemon.append($('<td/>').addClass('TotalBytes num').attr('value',dt))
			tdaemon.append($('<td/>').addClass(''))
			tdaemon_diff=$('<tr/>').attr('id','tdaemon-diff')
			tdaemon_diff.append($('<td/>').addClass('deviceName a-r br').text('difference'))
			tdaemon_diff.append($('<td/>').addClass('downloads num'))
			tdaemon_diff.append($('<td/>').addClass('uploads num br'))
			tdaemon_diff.append($('<td/>').addClass('TotalBytes num'))
			tdaemon_diff.append($('<td/>').addClass(''))
			return 
		}
		total+=dt
		utot+=up
		dtot+=down
		if(dnames[un]===undefined){
			dnames[un]={down:0, up:0}
		}
		dnames[un].down+=down
		dnames[un].up+=up
		var is_z=dt==0?' is_z':''
		if($("#"+did).length==0){
			var dc='d-un-'+u_n
			var nr=$('<tr/>').attr('id',did).addClass('is_d '+dc+is_z).attr('owner-name',un)
			var tcolour=devices[dmac].colour==null?colours_list[devices[dmac].un]:devices[dmac].colour
			nr.append($('<td/>').addClass('deviceName br').html("<span class='legend-colour' style='background:"+tcolour+"'></span>"+dn).attr('title', dmac+' | '+dip))
			nr.append($('<td/>').addClass('downloads num').attr('value',down))
			nr.append($('<td/>').addClass('uploads num br').attr('value',up))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',dt))
			nr.append($('<td/>').addClass('percent br'))
			if($('.'+dc).length>0){
				 $('.'+dc).last().after(nr)
			}
			else if($('#'+dc).length>0){
				 $('#'+dc).after(nr)
			}
			else{
				$(tag).append(nr)
			}
			$('#'+did+' .deviceName').click(function(){
				$('#mb-filter').val('dd-'+u_n+'-'+d_n).change()
			})
		}
		else{
			var arr=[[' .downloads',down], [' .uploads',up], [' .TotalBytes',dt]]
			updateRow(did,arr)
		}
	})
 	Object.keys(dnames).forEach(function(k){
		var u_n=clean(k)
		var uid='d-un-'+u_n
		var up=dnames[k].up,down=dnames[k].down,ut=up+down
		var is_z=ut==0?' is_z':''
		if($("#"+uid).length==0){
			var nr=$('<tr/>').attr('id',uid).addClass('is_u'+is_z)
			nr.append($('<td/>').addClass('userName br').text(k))
			nr.append($('<td/>').addClass('downloads num').attr('value',down))
			nr.append($('<td/>').addClass('uploads num br').attr('value',up))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',ut))
			nr.append($('<td/>').addClass('percent br'))
			$('.'+uid).first().before(nr)
			$('#'+uid+' .userName').click(function(){
				$('#mb-filter').val('dd-'+u_n).change()
			})
		}
		else{
			var arr=[[' .downloads',down], [' .uploads',up], [' .TotalBytes',ut]]
			updateRow(uid,arr)
		}
	})
	if($('#dailyFooter').html().length==0 && nrd>0){
		var nr=$('#dailyFooter').addClass('footer')
		nr.append($('<td/>').text(':::Totals:::').addClass('a-r br'))
		nr.append($('<td/>').addClass('downloads num').attr('value',dtot))
		nr.append($('<td/>').addClass('uploads num br').attr('value',utot))
		nr.append($('<td/>').addClass('TotalBytes num').attr('value',total))
		nr.append($('<td/>').text('-').addClass('a-c percent'))
		$('#dailyFooter').append(nr)
	}
	else{
		var arr=[[' .uploads',utot], [' .downloads',dtot], [' .TotalBytes',total]]
		updateRow('dailyFooter',arr)
	}
	if(tdaemon.length>0 && _traff_daemon==1){
		$('#dailyFooter').after(tdaemon)
		$('#tdaemon').after(tdaemon_diff)
		$('#tdaemon-diff .downloads').attr('value',$('#tdaemon .downloads').attr('value')-$('#dailyFooter .downloads').attr('value'))
		$('#tdaemon-diff .uploads').attr('value',$('#tdaemon .uploads').attr('value')-$('#dailyFooter .uploads').attr('value'))
		$('#tdaemon-diff .TotalBytes').attr('value',$('#tdaemon .TotalBytes').attr('value')-$('#dailyFooter .TotalBytes').attr('value'))
	}
	changelegend()
	setPercents('#DailyData tr, #correction-row', total)
	displayBytes('#daily-usage-table');
	$('#no-daily-data')[nrd==0?'slideDown':'slideUp']('slow')
	$('#daily-tab-section .changes-legend,#dailyFooter')[nrd==0?'slideUp':'slideDown']('slow')
}

function changelegend(){
	$('#changes-legend')[$('table .changed').length==0?'slideUp':'slideDown']('slow')
	$('#changes-legend .c0')[$('table .changed.c0').length==0?'hide':'show']()
	$('#changes-legend .c1')[$('table .changed.c1').length==0?'hide':'show']()
	$('#changes-legend .c2')[$('table .changed.c2').length==0?'hide':'show']()
	$('#changes-legend .c3')[$('table .changed.c3').length==0?'hide':'show']()
	$('#changes-legend .c4')[$('table .changed.c4').length==0?'hide':'show']()
	$('#changes-legend .c5')[$('table .changed.c5').length==0?'hide':'show']()

}
function setMonthlyTab(){
	var tag=$("#MonthlyData");
	var total=0,utot=0,dtot=0, traff_u=0,traff_d=0
	$('#mtdaemon, #mtdaemon-diff').remove()
	Object.keys(devices).sort(byName).forEach(function(k){
		var up=devices[k].up,down=devices[k].down,dt=up+down
		if(k=='FF:FF:FF:FF:FF:FF'){
			traff_u+=up
			traff_d+=down
			return
		}
		total+=dt
		utot+=up
		dtot+=down
		var is_z=dt==0?' is_z':''
		var did='mt-di-'+devices[k].id
		if($("#"+did).length==0){
			var un=devices[k].name
			var dn=devices[k].device
			var u_n=clean(un)
			var d_n=clean(dn)
			var tcolour=devices[k].colour==null?colours_list[devices[k].un]:devices[k].colour
			var nr=$('<tr/>').attr('id',did).addClass('is_d un-'+u_n+is_z).attr('owner-name',un)
			nr.append($('<td/>').addClass('deviceName br').html("<span class='legend-colour' style='background:"+tcolour+"'></span>"+dn).attr('title', k+' | '+devices[k].ip))
			nr.append($('<td/>').addClass('downloads num').attr('value',down))
			nr.append($('<td/>').addClass('uploads num br').attr('value',up))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',dt))
			nr.append($('<td/>').addClass('percent br'))
			$(tag).append(nr)
			$('#'+did+' .deviceName').click(function(){
				$('#mb-filter').val('dd-'+u_n+'-'+d_n).change()
			})
		}
		else{
			var arr=[[' .downloads',down], [' .uploads',up], [' .TotalBytes',dt]]
			updateRow(did,arr)
		}
	})
	Object.keys(names).forEach(function(k){
		var u_n=clean(k)
		var uid='mt-un-'+u_n
		var up=names[k].up,down=names[k].down,ut=up+down
		var is_z=ut==0?' is_z':''
		if($("#"+uid).length==0){
			var nr=$('<tr/>').attr('id',uid).addClass('is_u').addClass(is_z)
			nr.append($('<td/>').addClass('userName br').text(k))
			nr.append($('<td/>').addClass('downloads num').attr('value',down))
			nr.append($('<td/>').addClass('uploads num br').attr('value',up))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',ut))
			nr.append($('<td/>').addClass('percent br'))
			$('.un-'+k).first().before(nr)
			/*$('#'+uid+' .userName').click(function(){
				$('#mb-filter').val('dd-'+u_n).change()
			})*/
		}
		else{
			var arr=[[' .uploads',up], [' .downloads',down], [' .TotalBytes',ut]]
			updateRow(uid,arr)
		}
	})

	var c_up=0,c_down=0
	for(var d in corrections){
		if(corrections[d]){
			c_up+=corrections[d].up*toMB
			c_down+=corrections[d].down*toMB
	   }
	}
	$('#mcorrection-row .uploads').attr('value',c_up)
	$('#mcorrection-row .downloads').attr('value',c_down)
	$('#mcorrection-row .TotalBytes').attr('value',c_up+c_down)

	dtot+=c_down
	utot+=c_up
	total+=c_down+c_up

	if($('#monthlyFooter').html().length==0){
		var nr=$('#monthlyFooter').addClass('footer')
		nr.append($('<td/>').text(':::Totals:::').addClass('a-r br'))
		nr.append($('<td/>').addClass('downloads num').attr('value',dtot))
		nr.append($('<td/>').addClass('uploads num br').attr('value',utot))
		nr.append($('<td/>').addClass('TotalBytes num').attr('value',total))
		nr.append($('<td/>').text('-').addClass('a-c percent'))
		$('#monthlyFooter').append(nr)
	}
	else{
		var arr=[[' .downloads',dtot], [' .uploads',utot], [' .TotalBytes',total]]
		updateRow('monthlyFooter',arr)
	}
	
	if(_traff_daemon==1){
		var tdaemon=$('<tr/>').attr('id','mtdaemon')
		tdaemon.append($('<td/>').addClass('deviceName br a-r').text('traff daemon'))
		tdaemon.append($('<td/>').addClass('downloads num').attr('value',traff_d))
		tdaemon.append($('<td/>').addClass('uploads num br').attr('value',traff_u))
		tdaemon.append($('<td/>').addClass('TotalBytes num').attr('value',traff_d+traff_u))
		tdaemon.append($('<td/>').addClass(''))
		var tdaemon_diff=$('<tr/>').attr('id','mtdaemon-diff')
		tdaemon_diff.append($('<td/>').addClass('deviceName br a-r').text('difference'))
		tdaemon_diff.append($('<td/>').addClass('downloads num'))
		tdaemon_diff.append($('<td/>').addClass('uploads num br'))
		tdaemon_diff.append($('<td/>').addClass('TotalBytes num'))
		tdaemon_diff.append($('<td/>').addClass(''))
		$('#monthlyFooter').after(tdaemon)
		$('#mtdaemon').after(tdaemon_diff)
		$('#mtdaemon-diff .downloads').attr('value',$('#mtdaemon .downloads').attr('value')-$('#monthlyFooter .downloads').attr('value'))
		$('#mtdaemon-diff .uploads').attr('value',$('#mtdaemon .uploads').attr('value')-$('#monthlyFooter .uploads').attr('value'))
		$('#mtdaemon-diff .TotalBytes').attr('value',$('#mtdaemon .TotalBytes').attr('value')-$('#monthlyFooter .TotalBytes').attr('value'))
	}

	setPercents('#MonthlyData tr,#mcorrection-row', total)
	displayBytes('#monthly-totals-table');
}
function clean(n){
	return n.replace(' ','_').replace(/\W/g, "")
}
function updateRow(did,arr){
	arr.forEach(function(i){
		updateValue('#'+did+i[0],i[1])
	})
}
function updateValue(vid,v){
	var base=$("#DisplayBase").val();
	var dec=$("#NumDecimals").val()||2;
	var delta=v-$(vid).attr('value')
	if(delta!=0){
		var deltaIndex=Math.floor(Math.log(Math.abs(delta))/Math.log(base));
		var delta_val=(delta/Math.pow(base,Math.floor(deltaIndex))).toFixed(dec);
		var units=dispUnits[deltaIndex]+'ytes';
		var nstars=Math.floor(Math.log(delta)/Math.log(base));
		var msg='delta: '+delta_val + ' ' + units
		$(vid).attr('value',v).addClass('changed c'+nstars).attr('title',msg)
	}
}
function DrawPie(m_d){
	var data, datarows=[],devicecolours=[],tmp=[], mac
	var options={width:500,height:300,is3D:true};
	data=new google.visualization.DataTable();
	data.addColumn('string','User/Device');
	data.addColumn('number','MB Used');
	var dec=$("#NumDecimals").val()||2;
	if ($("#ShowDevices").is(":checked")){
		$('#'+m_d+'Data .is_d').not('.is_z').each(function(){
			var ca=($(this).find('.TotalBytes').attr('value')/toMB).toFixed(dec)
			datarows.push([$(this).attr('owner-name')+'-'+$(this).find('.deviceName').text(), parseFloat(ca)])
			tmp=$(this).find('.deviceName').attr('title').split('|');
			mac=tmp[0].trim().toUpperCase();
			var tcolour=devices[mac].colour==null?colours_list[devices[mac].un]:devices[mac].colour
			devicecolours.push(tcolour);
		})
		options.title='Percentage of '+m_d+' Usage By Device (MB)';
	}
	else{
		$('#'+m_d+'Data .is_u').not('.is_z').each(function(){
			var ca=($(this).find('.TotalBytes').attr('value')/toMB).toFixed(dec)
			datarows.push([$(this).find('.userName').text(), parseFloat(ca)])
		})
		options.title='Percentage of '+m_d+' Usage By User';
	}
	if((m_d=='Daily') && ($('#correction-row .TotalBytes ').attr('value')!=0)){
		var ca=($('#correction-row .TotalBytes ').attr('value')/toMB).toFixed(dec)
		datarows.push(['Corrections', parseFloat(ca)])
	}
	else if((m_d=='Monthly') && ($('#mcorrection-row .TotalBytes ').attr('value')!=0)){
		var ca=($('#mcorrection-row .TotalBytes ').attr('value')/toMB).toFixed(dec)
		datarows.push(['Corrections', parseFloat(ca)])
	}
	data.addRows(datarows);
	var ChartObj=new google.visualization.PieChart(document.getElementById(m_d+'Graph'));
 	if ($("#ShowDevices").is(":checked")) {options.colors=devicecolours}
 	ChartObj.draw(data,options);
}
function monthlyBreakdown(){
	var tag=$("#MonthlyBreakdown");
	var total=0,utot=0,dtot=0,traff_u=0,traff_d=0
	$('#mb-tdaemon, #mb-tdaemon-diff').remove()
	var dec=$("#NumDecimals").val()||2;
	mb_dates=[]
	traff=[]
	g_router=[]
	g_isp=[]
	g_ispdelta=[]
	g_cummulative=[]
	var syr=_rs_Date.getFullYear()
	var smo=_rs_Date.getMonth()

	var mbfs=$("#mb-filter option:selected")
	var sel=mbfs.val().split('-');
	var un=sel[1]
	if(mbfs.hasClass('ddl-u')){
		var dataset=getUsage('name',$("#mb-filter option:selected").text())
	}
	else if(mbfs.hasClass('ddl-d')){
		var id=(mbfs.attr('id')).replace('mbd-','')
		var mac=getDevice('id',id)
		var dataset=getUsage('mac',mac)
	}
	else{
		var dataset=usage
	}
	var showISP=$('#showISP').is(':checked')&&(un=== "ALL");
	var cap=Number($('#bw_cap').val());

	dataset.forEach(function(k){
		var up=k.up,down=k.down,mbtot=up+down
		var day=k.date
		var mo=Number(day)>=_resetDay?smo:(smo-(-1))
		var dt=new Date(syr,mo,day)
		var ds=syr+'-'+(mo+1)+'-'+day
		if(k.mac=='FF:FF:FF:FF:FF:FF'){
			traff_u+=up
			traff_d+=down
 			traff[ds]={dd:dt,down:down, up:up}
		   return
		}
		total+=mbtot
		utot+=up
		dtot+=down
		if(mb_dates[ds]===undefined){
			mb_dates[ds]={dd:dt,down:0, up:0}
		}
		mb_dates[ds].down+=down
		mb_dates[ds].up+=up
	})

	if(un=== "ALL"){
		for(var day in corrections){
			if(corrections[day]){
				var c_u=corrections[day].up*1
				var c_up=c_u*toMB
				var c_d=corrections[day].down*1
				var c_down=c_d*toMB
				var mo=Number(day)>=_resetDay?smo:(smo-(-1))
				var dt=new Date(syr,mo,day)
				var ds=syr+'-'+(mo+1)+'-'+twod(day)
				total+=c_up+c_down
				utot+=c_up
				dtot+=c_down
				if(mb_dates[ds]===undefined){
					mb_dates[ds]={dd:dt,down:0, up:0}
				}
				mb_dates[ds].down+=c_down
				mb_dates[ds].up+=c_up
				mb_dates[ds].hasCorrection=true
				mb_dates[ds].desc=corrections[day].desc+' (download -> '+c_d+'MB; upload -> '+c_u+'MB)'

		   }
		}
	}
	var cTot=0,ls_u,ls_d,ls_t=0,ls_ut=0,ls_dt=0,ls_ct=0,td_u=0,td_d=0,td_ct=0,td_di=0,td_cdi=0
	Object.keys(mb_dates).sort(function(a, b) { return (mb_dates[a].dd > mb_dates[b].dd?1:(mb_dates[a].dd < mb_dates[b].dd?-1:0)) }).forEach(function(d){
		var uid='mb-d-'+d
		var up=mb_dates[d].up,down=mb_dates[d].down,dt=up+down
		cTot+=dt
		var is_z=dt==0?' is_z':''
		if(localStorage.getItem('isp-'+d)){
			var ls_data = localStorage.getItem('isp-'+d).split(';')
			ls_u=Number(ls_data[0])
			ls_d=Number(ls_data[1])
		}
		else{
			ls_u=0
			ls_d=0
		}
		if(traff[d]){
			td_u=Number(traff[d].up)
			td_d=Number(traff[d].down)
		}
		else{
			td_u=0
			td_d=0
		}
		td_ct+=(td_u+td_d)

		ls_ut+=ls_u*toMB
		ls_dt+=ls_d*toMB
		ls_t=(ls_u+ls_d)*toMB
		ls_ct+=ls_t
		td_di=td_d+td_u==0 ? 0 : td_d+td_u-dt
		td_cdi+=td_di
		var dtot = ls_t-dt;
		var isp=((dtot>0?dtot:0)/toGB).toFixed(2)
		var router=((dtot>0?0:dtot)/toGB).toFixed(2)
		var diff=(ls_ct-cTot)/toGB.toFixed(2)

		if($("#"+uid).length==0){
			var nr=$('<tr/>').attr('id',uid).addClass('mb-row'+is_z)
			var da=mb_dates[d].dd.getDate()
			var mo=mb_dates[d].dd.getMonth()+1
			var yr=mb_dates[d].dd.getFullYear()
			nr.append($('<td/>').addClass('mbd-date a-r br').text(mb_dates[d].dd.toDateString()).attr('value',yr+'-'+mo+'-'+da).attr('title',mb_dates[d].desc))
			nr.append($('<td/>').addClass('downloads num').attr('value',down))
			nr.append($('<td/>').addClass('uploads num br').attr('value',up))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',dt))
			nr.append($('<td/>').addClass('aggTot num br2').attr('value',cTot))

			nr.append($('<td/>').addClass('ispd isp MBytes').html("<input type='text' value='"+ls_d+"' name='ispd-"+da+"'>"))
			nr.append($('<td/>').addClass('ispu isp MBytes br').html("<input type='text' value='"+ls_u+"' name='ispu-"+da+"'>"))
			nr.append($('<td/>').addClass('isp TotalBytes num br').attr('value',ls_t))
			nr.append($('<td/>').addClass('isp iaggTotal num br2').attr('value',ls_ct))
			nr.append($('<td/>').addClass('deltaBytes isp num br').attr('value',ls_t-dt))
			nr.append($('<td/>').addClass('isp daggTotal num br2').attr('value',ls_ct-cTot))
			
			if(_traff_daemon=='1'){
				nr.append($('<td/>').addClass('is_td num').attr('value',td_d))
				nr.append($('<td/>').addClass('is_td num br').attr('value',td_u))
				nr.append($('<td/>').addClass('is_td num br').attr('value',td_d+td_u))
				nr.append($('<td/>').addClass('is_td num num br2').attr('value',td_ct))
				nr.append($('<td/>').addClass('is_td num br').attr('value',td_di))
				nr.append($('<td/>').addClass('is_td num br2').attr('value',td_cdi))
			}
			$('#MonthlyBreakdown').append(nr)
		}
		else{
			var arr=[[' .downloads',down], [' .uploads',up], [' .TotalBytes',dt], [' .aggTot',cTot]]
			updateRow(uid,arr)
		}
		$('#'+uid+' .mbd-date')[mb_dates[d].hasCorrection==true?'addClass':'removeClass']('corrected')
		if(_traff_daemon=='1'){
			g_router.push([d,Number((down/toMB).toFixed(dec)),Number((up/toMB).toFixed(dec)),Number((td_u+td_d)/toMB.toFixed(dec))])
			g_cummulative.push([d,Number((cTot/toGB).toFixed(dec)),Number((ls_ct/toGB).toFixed(dec)),Number((td_ct/toGB).toFixed(dec)),Number(diff.toFixed(dec)),cap])
		}
		else{
			g_router.push([d,Number((down/toMB).toFixed(dec)),Number((up/toMB).toFixed(dec))])
			g_cummulative.push([d,Number((ls_ct/toGB).toFixed(dec)),Number((cTot/toGB).toFixed(dec)),Number(diff.toFixed(dec)),cap])
	  }
		g_isp.push([d,Number(ls_d),Number(ls_u)])
		g_ispdelta.push([d,Number(isp),Number(router),Number(diff.toFixed(dec))])
	})

	if($('#breakdownFooter').html().length==0){
		var nr=$('<tr/>').attr('id','bdFooter').addClass('footer')
		nr.append($('<td/>').text(':::Totals:::').addClass('a-r br'))
		nr.append($('<td/>').addClass('downloads num').attr('value',dtot))
		nr.append($('<td/>').addClass('uploads num br').attr('value',utot))
		nr.append($('<td/>').addClass('TotalBytes num').attr('value',total))
		nr.append($('<td/>').text('-').addClass('a-c br2'))
		nr.append($('<td/>').addClass('isp num').attr('value',ls_dt).attr('id','isp-dt'))
		nr.append($('<td/>').addClass('isp num br').attr('value',ls_ut).attr('id','isp-ut'))
		nr.append($('<td/>').addClass('isp num br').attr('value',ls_ct).attr('id','isp-t'))
		nr.append($('<td/>').text('-').addClass('isp a-c br2'))
		nr.append($('<td/>').text('-').addClass('isp a-c br'))
		nr.append($('<td/>').addClass('isp isp GBytes num br2').attr('value',ls_ct-cTot))
		if(_traff_daemon==1){
			nr.append($('<td/>').addClass('downloads num').attr('value',traff_d))
			nr.append($('<td/>').addClass('uploads num br').attr('value',traff_u))
			nr.append($('<td/>').addClass('TotalBytes num').attr('value',traff_d+traff_u))
			nr.append($('<td/>').text('-').addClass('a-c br2'))
			nr.append($('<td/>').text('-').addClass('a-c br'))
			nr.append($('<td/>').addClass('num br2').attr('value',td_cdi))
		}
		$('#breakdownFooter').append(nr)
	}
	else{
		var arr=[[' .downloads',dtot], [' .uploads',utot], [' .TotalBytes',total]]
		updateRow('bdFooter',arr)
		updateISPTotals()
	}

	if(_traff_daemon=='1'){
		$('.is_td').show()
	}

	displayBytes('#MonthlyBreakdown,#breakdownFooter');
	if(_traff_daemon=='1'){
		var router_options={width:500,height:400,title:'Router measured traffic (in MB)',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'MB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'#800000',visibleInLegend:true},2:{type: "line",color:'green',visibleInLegend:true}}};
	}
	else{
		var router_options={width:500,height:400,title:'Router measured traffic (in MB)',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'MB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'#800000',visibleInLegend:true}}};
	}
	BarChart('RouterGraph',g_router,router_options,_traff_daemon)
	console.log(traff)
	if(showISP){
		var isp_options={width:500,height:400,title:'ISP recorded traffic (in MB)',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'MB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'#800000',visibleInLegend:true}}};
		BarChart('ISPGraph',g_isp,isp_options,0)
		BarLineChart('ISPDelta',g_ispdelta)
		LineChart('CummulativeGraph',g_cummulative)
		ISP_Change()
	}
	$('.correction-note')[$('tr .corrected').length==0?'hide':'show']()
	$('.mbd-date').click(function(){
		var dt=$(this).attr('value').split('-')
		_cr_Date=new Date(dt[0],dt[1]-1,dt[2])
		$('#daily-tab').removeClass('loaded');
		load_view('daily-tab',true);
	})

}
function BarChart(s,d,baroptions,addline){
	var data;
	var options={width:500,height:440,is3D:true};
	data=new google.visualization.DataTable();
	data.addColumn('string','Day');
	data.addColumn('number','Downloaded (in MB)');
	data.addColumn('number','Uploaded (in MB)');
	if(addline=='1'){
		data.addColumn('number','Traff Daemon (in MB)');
	}
	data.addRows(d);
	var chart=new google.visualization.ColumnChart(document.getElementById(s));
	chart.draw(data,baroptions);
}
function BarLineChart(s,d){
	var data;
	var options={width:500,height:440,is3D:true};
	data=new google.visualization.DataTable();
	data.addColumn('string','Day');
	data.addColumn('number','Router');
	data.addColumn('number','ISP');
	var baroptions={width:500,height:400,seriesType: "bars",title:'Difference between Router & ISP',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'GB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'green',visibleInLegend:true},2:{type: "line",color:'red',visibleInLegend:true}}};
	data.addColumn('number','Cummulative Difference');
	data.addRows(d);
	var chart=new google.visualization.ColumnChart(document.getElementById(s));
	chart.draw(data,baroptions);
}
function LineChart(s,d,baroptions){
	var data;
	var options={width:500,height:440,is3D:true};
	data=new google.visualization.DataTable();
	data.addColumn('string','Day');
	data.addColumn('number','Router');
	data.addColumn('number','ISP');
	if(_traff_daemon=='1'){
		data.addColumn('number','Traff');
		var baroptions={width:500,height:400,title:'Accummulated Totals',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{f:'green'}},vAxis:{title:'GB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'green',visibleInLegend:true},2:{color:'green',visibleInLegend:true},3:{color:'red',visibleInLegend:true},4:{color:'black',visibleInLegend:true}}};
	}
	else{
		var baroptions={width:500,height:400,title:'Accummulated Totals',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'GB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'green',visibleInLegend:true},2:{color:'red',visibleInLegend:true},3:{color:'black',visibleInLegend:true}}};
	}
	data.addColumn('number','Cummulative Difference');
	data.addColumn('number','Monthly Allowed');
	data.addRows(d);
	var baroptions={width:500,height:400,title:'Accummulated Totals',legend:{position:'top'},chartArea:{width:'80%',height:'70%'},isStacked:true,hAxis:{textStyle:{fontSize:7},title:$('.current-interval').first().text(),slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'GB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'green',visibleInLegend:true},2:{color:'red',visibleInLegend:true},3:{color:'black',visibleInLegend:true}}};
	var chart=new google.visualization.LineChart(document.getElementById(s));
	chart.draw(data,baroptions);
}
function UsageHistoryChart(){
	if($('.summary-row').length==1) return;
	var dec=$("#NumDecimals").val()||2;
	var g_usage=[]
	if($('#bandwidth-l').is(':checked')){
		 var cap=Number($('#bw_cap').val())
	}
	$('.summary-row').each(function(){
		var t=$(this).attr('id').split('-')
		var cI=t[2]+'-'+t[3]
		var up=Number(($(this).find('.uploads').attr('value')/toGB).toFixed(dec))
		var down=Number(($(this).find('.downloads').attr('value')/toGB).toFixed(dec))
		if($('#bandwidth-l').is(':checked')){
			g_usage.push([cI,down,up,cap]);
		}
		else{
			g_usage.push([cI,down,up]);
		}
	})
	var data;
	data=new google.visualization.DataTable();
	data.addColumn('string','Billing Interval');
	data.addColumn('number','Downloads');
	data.addColumn('number','Uploads');
	if($('#bandwidth-l').is(':checked')){
		data.addColumn('number','Usage Allowance');
	}
	data.addRows(g_usage.reverse());
	var ht=$('#summary-tab-section').height()
	var baroptions={
		width:400,height:ht,seriesType: "bars",title:'Monthly Utilization',legend:{position:'top'},chartArea:{width:'80%',height:'40%'},isStacked:true,hAxis:{title:'Month',slantedText:true,titleTextStyle:{color:'green'}},vAxis:{title:'GB',titleTextStyle:{color:'green'}},series:{0:{color:'blue',visibleInLegend:true},1:{color:'green',visibleInLegend:true},2:{type: "line",color:'red',visibleInLegend:true}}
	};
	var UsageChart=new google.visualization.ColumnChart(document.getElementById('UsageGraph'));
	UsageChart.draw(data,baroptions);
	$('#UsageGraph').attr('style','float:right')
}
function ISP_Change(){
	if(!$('#showISP').is(':checked')) return;
	$('.ispu input, .ispd input').change(function(){
		$(this).removeClass('badvalue');
		if(isNaN($(this).val())){
			$(this).addClass('badvalue');
			$(this).select();
		}
		else{
			var row=$(this).parents('tr');
			var row_id=row.attr('id').split('-');
			var isp_date=row_id[2] + '-' + row_id[3] + '-' + row_id[4];
			var isp_u=Number(row.find('.ispu input').val())
			var isp_d=Number(row.find('.ispd input').val())
			var tb =Number(row.find('.TotalBytes ').attr('value'))
			var tot=(isp_u+isp_d)*toMB
			row.find('.isp.TotalBytes').attr('value',(tot).toFixed(0))
			row.find('.deltaBytes').attr('value',(tot-tb))
			displayBytes('#MonthlyBreakdown');
			var isp_data=isp_u+';'+isp_d
			localStorage.setItem('isp-'+isp_date,isp_data)
			updateISPTotals()
		}
	})
}
function updateISPTotals(){
	var tu=0,td=0
	$('.mb-row').each(function(){
		var dd=$(this).find('.ispd input').val()*toMB,du=$(this).find('.ispu input').val()*toMB
		tu+=du
		td+=dd
	})
	$('#isp-dt').attr('value',td)
	$('#isp-ut').attr('value',tu)
	$('#isp-t').attr('value',td+tu)
	displayBytes('#breakdownFooter');

}
function byName(a,b) {
	var n1=devices[a].name.toLowerCase()
	var n2=devices[b].name.toLowerCase()
	return ((n1<n2)?-1:((n1>n2)?1:byDevice(a,b)));
}
function byDevice(a, b) {
	var d1=devices[a].device.toLowerCase()
	var d2=devices[b].device.toLowerCase()
	return ((d1<d2)?-1:((d1>d2)?1:0));
}
function setDevicesTab(){
	var tag=$("#devicesData");
	var total=0
	Object.keys(devices).sort(byName).forEach(function(k){
		var dt=devices[k].up+devices[k].down
		total+=dt
		var is_z=dt==0?' is_z':''
		var did='dt-'+devices[k].id
		if($('#'+did).length==0){
			var nr=$('<tr/>').attr('id',did).addClass('is_d').addClass(is_z)
			nr.append($('<td/>').addClass('userName').text(devices[k].name))
			nr.append($('<td/>').addClass('deviceName').text(devices[k].device))
			nr.append($('<td/>').addClass('deviceIP').text(devices[k].ip))
			nr.append($('<td/>').addClass('deviceMAC').text(k))
			nr.append($('<td/>').addClass('TotalBytes num br').attr('value',dt))
			nr.append($('<td/>').addClass('percent br'))
			$(tag).append(nr)
		}
		else{
			var arr=[[' .TotalBytes',dt]]
			updateRow(did,arr)
		}
	})
	if($('#devicesFooter').length==0){
		var nr=$('<tr/>').attr('id','devicesFooter').addClass('footer')
		nr.append($('<td/>').attr('colspan',4).text(':::Totals:::').addClass('a-r'))
		nr.append($('<td/>').addClass('TotalBytes num').attr('value',total))
		nr.append($('<td/>').text('-').addClass('a-c br percent'))
		$('#devicesData').append(nr)
	}
	else{
		var arr=[[' .TotalBytes',total]]
		updateRow('devicesFooter',arr)
	}

	setPercents('#devicesData tr', total)
	displayBytes('#devices-table');
}
function setPercents(rows, tot){
	var dec=$("#NumDecimals").val()||2;
	var ctot=0
	$(rows).each(function(){
		var dt=Number($(this).find('.TotalBytes').attr('value'));
		var dp=dt/tot * 100
		ctot+=($(this).hasClass('is_d')?dp:0)
		dp=(dp > 0.1)? dp.toFixed(dec):"-";
		var pcu=(dp > 100?'over-cap':(dp > 90?'cap-90':(dp > 80?'cap-80':(dp > 40?'cap-40':'cap-ok'))))
		$(this).find('.percent').text(dp).removeClass('over-cap cap-90 cap-80 cap-40 cap-ok').addClass(pcu)
	})
	$(rows).parents('table').find('.footer .percent').text(ctot.toFixed(dec))
}
function displayBytes(range,override){
	var aggTotal=0,iaggTotal=0,daggTotal=0;
	$('.mb-row').each(function(){
		var total=Number($(this).children('.TotalBytes').not('.isp').attr('value'));
		aggTotal+=total;
		var itotal=Number($(this).children('.isp.TotalBytes').attr('value'));
		iaggTotal+=itotal;
		var dtotal=Number($(this).children('.deltaBytes').attr('value'));
		daggTotal+=dtotal;
		var changed=$(this).children('.uploads').hasClass('changed')||$(this).children('.downloads').hasClass('changed')?'changed':''
		$(this).children('.aggTotal').attr('value',aggTotal).addClass(changed)
		$(this).children('.iaggTotal').attr('value',iaggTotal)
		$(this).children('.daggTotal').attr('value',daggTotal)
	})

	var default_units=$("#DisplayUnits").val();
	var decimals=$("#NumDecimals").val()||2;
	var base=$("#DisplayBase").val();
	var cells= $(range).find('.num');
	$(cells).removeClass('bytes Kbytes MBytes GBytes TBytes PBytes negative');
	$(cells).each(function(){
		var cell_val='N/A';
		var units='';
		var isneg='';
		var bytes=Number($(this).attr('value'));
		if (isNaN(bytes)){
		}
		else{
			var unitsIndex=(default_units=== "auto")?(Math.floor((bytes==0?0:Math.log(Math.abs(bytes)))/Math.log(base))):default_units;
			unitsIndex=override||unitsIndex;
			cell_val=(bytes/Math.pow(base,Math.floor(unitsIndex))).toFixed(decimals);
			units=dispUnits[unitsIndex]+'ytes';
			isneg=cell_val<0?' negative':'';

		}
		$(this).html(cell_val).addClass(units+isneg);
	})
}
function showHideDevices(){
	var sz=$('#ShowZeroes').is(':checked')
	var sd=$('#ShowDevices').is(':checked')
	$('.TotalBytes').not('.isp').each(function(){
		var tp = $(this).parent('tr')
		if(tp.hasClass('summary-row')){
		   return
		}
		var bytes=$(this).attr('value');
		var is_z=(bytes==0);
		var is_d=tp.hasClass('is_d') ;
		var is_v=$(this).is(':visible')
		var tid=tp.attr('id')
		if(!is_d||(is_d&&sd)){
			if (is_z&&sz&&!is_v) {
				tp.slideDown('slow')
		   }
			else if(is_z&&!sz&&is_v){
				tp.slideUp('slow')
		   }
			else if(!is_z&&!is_v){
				tp.slideDown('slow')
		   }
		}
		else if(is_d&&!sd){
			if(is_v){
				tp.slideUp('slow')
			}
		}
		else if(!is_v){
			tp.slideDown('slow')
		}
	})
	$('.ddl-device')[sd?'removeClass':'addClass']('hidden');
	$('.isp')[$('#showISP').is(':checked')&&$('#mb-filter').val()=='dd-ALL'?'removeClass':'addClass']('hidden');
	$('.is-cap')[$('#bandwidth-u').is(':checked')?'hide':'show']()
	$('#correction-row')[$('.cf-desc').val()==''&&$('#correction-row .TotalBytes').attr('value')==0?'hide':'show']()
	$('#mcorrection-row')[$('#mcorrection-row .TotalBytes').attr('value')==0?'hide':'show']()
	if($('#correction-row').is(':visible')){
		$('#dailyFooter').show()
	}
	if($('#mcorrection-row').is(':visible')){
		$('#monthlyFooter').show()
	}
	if($('#daily-tab').hasClass('loaded'))DrawPie('Daily');
	if($('#monthly-tab').hasClass('loaded'))DrawPie('Monthly');
}
function getDevice(p,v){
	var r,va=''
	 Object.keys(devices).forEach(function(d){
		switch(p){
			case 'device':
				if(devices[d].device==v){
					r=d
				}
				break
			case 'id':
				if(devices[d].id==v){
					r=d
				}
				break
		   case 'ip':
				if(devices[d].ip==v){
					r=d
				}
				break
			default:
				break
		}
	})
	return r
}
function getUsage(p,v){
	var r=[]
	usage.forEach(function(k){
		if(k[p]==v) r.push(k)
	})
	return r.sort(function(a, b) { return (a.name > b.name?1:(a.name < b.name?-1:0)); })
}
function flushChanges(){
	$('.num').attr('title','').removeClass('changed c0 c1 c2 c3 c4 c5');
}
function newdate(d,o){
	return new Date(d.getFullYear(),d.getMonth(),d.getDate()+o);
}
function delLS(i) {
	if(confirm('Are you sure you want to delete this history entry?\nThis will also reload the data.')){
		$('#'+i).remove()
		localStorage.removeItem(i)
		var fn=$('.currentSummary').attr('id')
		load_data(fn)
	}
}
function addcorrection(){
	$('#correction-row,#remove-correction').slideDown('slow')
	$('#no-daily-data,#add-correction').slideUp('slow')
}
function removecorrection(){
	if(confirm('Are you sure you want to delete the correction for this date?')){
		$('#correction-row input').val('').change()
		$('#correction-row,#remove-correction').slideUp('slow')
		$('#add-correction').slideDown('slow')
		$('#no-daily-data')[$('#DailyData tr').length==0?'slideDown':'slideUp']('slow')
		$('#dailyFooter')[$('#DailyData tr').length==0?'slideUp':'slideDown']('slow')
		$('#MonthlyBreakdown').html('')
	}
}
function settings(wo){
	if(wo=='reset'){
		if(!confirm('Are you sure that you want to clear all localStorage variables stored for YAMon?')){
			return
		}
		localStorage.Clear()
	}
	else if(wo=='export'){
		$('#SECTION_TWO').append("<div id='settings'><h3>Export Settings</h3><p>All of the settings, etc. for this web app are retained in localStorage (meaning that they are private to this browser on this computer).  This is my quick & dirty method (emphasis on the latter) for copying your settings to different browser or device.</p><p>Copy the text from the field below to a file on a USB stick or email it to yourself and then open the `Settings` tab on the other machine (or browser) and click `Import`.</p><textarea rows=16 cols=80></textarea><p><button onclick=close_settings()>Close</button></p>")
		var ts=JSON.stringify(localStorage)
		$('#settings textarea').val(ts)
	}
	else{
		$('#SECTION_TWO').append("<div id='settings'><h3>Import Settings</h3><p>Paste the settings you exported previously into the field below and then click `Import`.</p><p><b>NOTE</b> - this replace all similarly named variables within the localStorage for this browser on this machine.  <i>It cannot be undone!</i>  I strongly recommend that you first export the settings from this machine... just in case!</p><textarea rows=16 cols=80></textarea><p><button onclick=import_settings()>Import</button><button onclick=close_settings()>Cancel</button></p>")
	}
}
function close_settings(){
	$('#settings').slideUp('slow').remove()
}
function import_settings(){
	if(!confirm("Are you sure you want to do this?  Have you already backed up the settings from this machine (by exporting them)?\n\nRemember that you cannot undo this operation without a backup... you've been warned!  Click `Cancel` to chicken out.")){
		close_settings()
		return false
	}
	var nv=JSON.parse($('#settings textarea').val())
	Object.keys(nv).forEach(function(k){
		localStorage.setItem(k,nv[k])
	})
	location.reload();
}
function changeUnits(wo){
	var ct=$(wo).text().toLowerCase()
	var ns=ct=='auto'?ct:2
	$('#DisplayUnits').val(ns).change()
	$('.change-units a').hide();
	$('.change-units a')[$('#DisplayUnits').val()=='auto'?'first':'last']().show()

}